﻿#ifndef MSERIALPORTLIST_H
#define MSERIALPORTLIST_H

#include <QThread>
#include <QObject>
#include <QTimer>
#include <QSerialPortInfo>
#include <QMetaType>
#include <QMutex>

#ifndef DEBUG
    #define DEBUG    1
#endif
#define SERIAL_SCANNING_CYCLE_MS    200 /*!< 定义串口扫描周期，单位：ms */

#ifdef QT_NO_DEBUG
    #define Q_SERIAL_PORT_LIST_DEBUG    0
#else
    #define Q_SERIAL_PORT_LIST_DEBUG    (1 && DEBUG)
#endif

#define TAG_LOG(type, fmt, ...) \
    do { \
        QString str2; \
        str2.sprintf(fmt, ##__VA_ARGS__); \
        type() << str2.toUtf8().data(); \
    } while(0)

#ifndef TAG_DEBUG
    #if Q_SERIAL_PORT_LIST_DEBUG
        #define TAG_DEBUG(fmt, ...) TAG_LOG(qDebug, fmt, ##__VA_ARGS__)
    #else
        #define TAG_DEBUG(fmt, ...) ((void)0)
    #endif
#endif
#ifndef TAG_INFO
    #define TAG_INFO(fmt, ...)      TAG_LOG(qInfo, fmt, ##__VA_ARGS__)
#endif
#ifndef TAG_ERROR
    #define TAG_ERROR(fmt, ...)     TAG_LOG(qCritical, fmt, ##__VA_ARGS__)
#endif
#ifndef TAG_WARNING
    #define TAG_WARNING(fmt, ...)   TAG_LOG(qWarning, fmt, ##__VA_ARGS__)
#endif

#ifndef Q_SERIAL_PORT_INFO_LIST_TYPEDEF
    #define Q_SERIAL_PORT_INFO_LIST_TYPEDEF
    typedef  QList<QSerialPortInfo>  QSerialPortInfoList;
#endif

class MSerialPortList : public QThread
{
    Q_OBJECT

public:
    static MSerialPortList *instance(void);

    const QSerialPortInfo &get_select_serial(void);
    int set_select_serial(const QSerialPortInfo &serial);
    int set_select_serial(const QString &port_name);

    int scanning_start(void);
    int scanning_stop(void);

protected:
    MSerialPortList(qint16 cycle_ms, QObject *parent = nullptr);
    ~MSerialPortList();
    void run(void) Q_DECL_OVERRIDE;

private:
    qint16 scanning_cycle_ms;   /*!< 串口扫描周期 */
    QTimer scanning_timer;      /*!< 扫描定时器 */
    bool scanning_start_flag;   /*!< 开始扫描标志位 */

    QSerialPortInfoList serial_ports_info_list;
    QSerialPortInfo select;

    QMutex mutex_scanning;
    QMutex mutex_update;

protected slots:
    void on_scanning_timer_timeout(void);

signals:
    void new_serial_port_update(const QSerialPortInfoList &);
};

#endif // MSERIALPORTLIST_H
